package com.zzyl.nursing.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zzyl.common.exception.ServiceException;
import com.zzyl.nursing.service.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class WechatServiceImpl implements WechatService {

    private static final String GET_PHONE_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    private static final String GET_OPENID_URL = "https://api.weixin.qq.com/sns/jscode2session";

    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    @Autowired
    private RedisTemplate redisTemplate;

    @Value(value = "${wechat.appId}")
    private String appid;

    @Value(value = "${wechat.appSecret}")
    private String secret;

    @Override
    public String getOpenId(String code) {
        String result = HttpRequest.get(GET_OPENID_URL)
                .form("appid", appid)
                .form("secret", secret)
                .form("js_code", code)
                .form("grant_type", "authorization_code")
                .timeout(5000)
                .execute().body();
        JSONObject jsonObject = JSONUtil.parseObj(result);
        log.info("获取openid的结果,{}", jsonObject);
        String openid = jsonObject.getStr("openid");
        if (StrUtil.isEmpty(openid)) {
            throw new ServiceException("获取openid失败, 请稍后再试");
        }
        return openid;
    }


    @Override
    public String getPhoneNumber(String phoneCode) {
        Map<String, String> map = Collections.singletonMap("code", phoneCode);
        String result = HttpRequest.post(GET_PHONE_URL + getAccessToken())
                .body(JSONUtil.toJsonStr(map))
                .timeout(5000)
                .execute().body();
        log.info("获取手机号码的结果 = " + result);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        String phoneNumber = jsonObject.getByPath("phone_info.phoneNumber", String.class);
        if (StrUtil.isEmpty(phoneNumber)) {
            throw new ServiceException("获取手机号码失败，请稍后重试");
        }
        return phoneNumber;
    }

    /**
     * 获取微信授权 有效期为2小时
     * 优化：access_token缓存到redis，设置有效期为1小时50分钟
     * 获取是优先从redis取
     *
     * @return
     */
    private String getAccessToken() {
        String accessToken = (String) redisTemplate.opsForValue().get("wechat:accessToken");
        if (!StrUtil.isEmpty(accessToken)) {
            log.info("accessToken缓存命中,{}",accessToken);
            return accessToken;
        }
        String result = HttpRequest.get(ACCESS_TOKEN_URL)
                .form("grant_type", "client_credential")
                .form("appid", appid)
                .form("secret", secret)
                .timeout(5000)
                .execute().body();
        JSONObject jsonObject = JSONUtil.parseObj(result);
        log.info("获取微信授权: {}", jsonObject);
        accessToken = jsonObject.getStr("access_token");
        redisTemplate.opsForValue().set("wechat:accessToken",accessToken,110, TimeUnit.MINUTES);
        if (StrUtil.isEmpty(accessToken)) {
            throw new ServiceException("获取微信授权失败，请稍后重试");
        }
        return accessToken;
    }
}
